//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CLocalFileSystem.h>
///	@path	~/src/database/xres/
///	@date	2007/11/24
///	@desc	.

#pragma once

#include "xeres.h"

#include <map>

#include "lib/system/file_op.h"

#include "database/database.h"
#include "database/store/IFileSystem.h"

namespace xeres {

	// forward declaration
	class IFileHandler;

	/*!
		\class	CLocalFileSystem
		\brief
	*/
	class CLocalFileSystem : public IFileSystem
	{
	public:

		/// \ctor
		CLocalFileSystem( void );

		/// \dtor
		virtual ~CLocalFileSystem( void );

		DECL_IOBJECT_CLASS( CLocalFileSystem , IFileSystem );

	public:

	//@ interface

		/*!
			\brief		Query file exists.
		*/
		virtual bool FileExist( const WString& path );

		/*!
			\brief		Query directory exists.
		*/
		virtual bool DirectoryExist( const WString& path );

		/*!
			\brief		Get specific file info.
		*/
		virtual bool GetFileInfo( const WString& path , DataInfo& info );

		/*!
			\brief		Create directory at specific location.
		*/
		virtual bool CreateDirectory( const WString& path );

		/*!
			\brief		Create file at specific location.
		*/
		virtual RefPass<IFile> CreateFile( const WString& path );

		/*!
			\brief		Open file at specific location.
		*/
		virtual RefPass<IFile> OpenFile( const WString& path );

		/*!
			\brief		Open POSIX type file handle.
		*/
		virtual FILE * OpenPosixFile( const char * path , const char * mode );

		/*! 
			\brief		Open IStream instance of file system (read-only).
		*/
		virtual IStream * OpenIStream( const WString& path );

		/*!
			\brief		Copy a file to specific location.
		*/
		virtual bool CopyFile( const WString& src , const WString& dst );

		/*!
			\brief		Delete a file from a specific location.
		*/
		virtual bool DeleteFile( const WString& path );

		/*!
			\brief		List a directory.
		*/
		virtual bool ListDir( const WString& path , const WString& spec , std::vector<WString>& files );

		/*!
			\brief		Enumerate files in a directory.
		*/
		virtual void EnumerateFiles( const WString& path , const WString& spec ,
			function<void(const IEnumFileData&)> handler );

		/*!
			\brief		Create corresponding data entry from file.
		*/
		virtual RefPass<IData> CreateEntryFromFile( const WString& path );

		/*!
			\brief		Load exist entry from file.
		*/
		virtual RefPass<IData> LoadEntryFromFile( const WString& path );

	//@ local

		/*!
			\brief		Set path base.
		*/
		bool SetPathBase( const WString& path );

		/*!
			\brief		Add excluded file.
		*/
		bool AddExclude( const WString& path );

		/*!
			\brief		Add new file handler.
		*/
		bool AddFileHandler( const WString& extensions , RefWeak<IFileHandler> handler );

	protected:

		/*!
			\brief		Get absolute path related to path base.
						Usually we set to application directory,
						overload it to redirect to another path.
		*/
		virtual std::vector<WString> GetRootPaths( void );

	private:


		// proxy of enumerate files
		static void ProxyEnumerateFiles( function<void(const IEnumFileData&)>* handler , const FileOp::EnumFileData& efd );

		// get full path base
		const WString& GetFullPathBase( void );

		// internal composite filename
		WString CompositePath( const WString& path );

	//@ data

		// file path base ( application_dir + resource_dir )
		WString					m_pathBase;
		WString					m_fullpathBase;
		AString					m_fullpathBaseA;

		// file handler
		std::map< Key , Ref<IFileHandler> >		m_fileHandlers;

	};

} // namespace xeres
